package events;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;

import dataStructures.Adjacencies;
import dataStructures.LSDataBase;
import dataStructures.NeighborDataStructure;
import dataStructures.NeighborTable;
import packets.LSA;
import packets.OSPF;
import packets.OSPFDescription;
import statemachine.DecisionPoint;

/**
 * Listener, der auf ein eingehendes OSPF Database Description Paket reagiert.
 * @author pascal
 *
 */
public class ReceiveDescriptionsListener implements ReceivePacketListener {

	@Override
	public void processPacket(ReceivedEvent event) {
		
		OSPFDescription descPacket = (OSPFDescription)event.getProtocolPacket(); 
		OSPF ospf = event.getProtocolPacket().getPacket().getHeader(new OSPF());
		
		try {
			NeighborDataStructure transmittingNeighbor = NeighborTable.getInstance().getNeighbor(InetAddress.getByAddress(ospf.routerID()), 
																									event.getSource().getRouterInterface());
				
			//Abgleich der Link-State Database mit den eingehenden Beschreibungen des Nachbarn
			ArrayList<LSA> descibingLSAs = descPacket.getLSAs();
			
			for(LSA lsa : descibingLSAs){
				if(!LSDataBase.getInstance().hasMoreRecent(lsa)){
					transmittingNeighbor.getLinkStateRequestList().add(lsa);
				}
			}
			
			//Falls der Zustand des Nachbarn "ExStart" ist, muss die Master Slave Beziehung zunächst ausgehandelt werden...
			if(transmittingNeighbor.getState().getName().equals("ExStart")){
				//... dazu wird ein leeres DatabaseDesciptionPacket gesendet
				event.getSource().getRouterInterface().sendDatabaseDescriptionPacket(transmittingNeighbor);
				
				//Falls beim eingehenden Paket das MS-Bit auf 0 gesetzt ist, ist dieser Router zukünftig der Master
				if((descPacket.IMMS() & 0x01) == 0 ){
					transmittingNeighbor.setMasterSlave(false);
					transmittingNeighbor.changeState("IE8");
					
				}
			}
			
			//Falls die MasterSlave Beziehung bereits ausgehandelt ist, folgt nun der Vergleich der Datenbanken
			else if(transmittingNeighbor.getState().equals("Exchange")){
				
				//Falls das M-Bit 0 ist, ist dies das letzte eingehende Description Paket und es folgt der Request
				if((descPacket.IMMS() & 0x02) == 0){
					transmittingNeighbor.changeState("IE9");
					
					//Der neue Zustand ist ein Entscheidungspunkt
					((DecisionPoint)transmittingNeighbor.getState()).decide(transmittingNeighbor);
					
					//Falls der Zustand Loading ist, erfolgt der Austausch der benötigten LSAs
					if(transmittingNeighbor.getState().equals("Loading")){
							event.getSource().getRouterInterface().sendLinkStateRequestPacket(transmittingNeighbor);					
					}
					//Andernfalls ist der Nachbar Full und wird als adjazent betrachtet
					else Adjacencies.getInstance().addAdjacencie(transmittingNeighbor);
				}
			}
			
			
			
		} catch (UnknownHostException e) {
			
			e.printStackTrace();
		}
		
		

	}

}
